/**
 * CPU\Memory\NetWork Usage
 * @RequestMapping(value="/cp/service/detail/default/{Service Name}",path="容器服务 >实例 >监控")
 * @Refer  HighCharts API http://api.highcharts.com/highcharts/Series.update(
 * @Refer  http://www.hcharts.cn/demo/highcharts/line-basic
 * Created by hjqi on 2016/4/18.
 */
module.controller('InstanceMonitorController',
    function ($scope,$cookies,$stateParams,monitorService,k8sService,$interval) {

        //TODO load st 5 sec
        $scope.curId = undefined;
        if( ! $scope.curItem  ){
            $scope.curItem  = undefined;
        }
        var oneMegabyte = 1024 * 1024;
        var showStatusLength = 20;
        $scope.pods = [];
        var cpuloadInterval = undefined;
        var memloadInterval = undefined;
        var networkloadInterval = undefined;
        var networkrxloadInterval = undefined ;
        var IntervalSec = 5;
        var maxInterval = 3600 ;//3600s

        $scope.cpuSeries = [ {
            name:'cpu',
            data:[]
        }];
        $scope.cpuloadfunc = function () {

            var _curlst = [];
            var series = this.series[0];

            $scope.$watch('curId', function(newValue, oldValue) {
                if(newValue != undefined){
                    var msg = "CPU :"+newValue+"change to "+oldValue ;
                    load(newValue);
                }
            });
            //load(id);
            function load(id) {
                if(series.data.length === 0){
                    //run at the first time
                    monitorService.getCpuStatusDatas(id,0,20,$scope.svc.dbJson.node.clusterId).then(function(rets){
                        _curlst = rets.data.slice();
                       // var points = getInitCpuStatusData(_curlst);
                        var points1 = getInitCpuStatusData1 ( rets.data) ;
                        points1.forEach(function(one){
                            series.addPoint(one, true, series.data.length >= showStatusLength);
                        });
                    });
                }else{
                    monitorService.getCpuStatusDatas(id,IntervalSec,20,$scope.svc.dbJson.node.clusterId).then(function(rets){
                        if(rets.data.length != 0){
                            //console.log("rets.data.length ="+rets.data.length ) ; //length=9
                            if(rets.data.length == 1){
                                // var _d = getCpuStatusData(_curlst[_curlst.length - 1],rets.data[0]);
                                var _d = getCpuStatusData(_curlst[_curlst.length - 1],rets.data[0],true);
                                series.addPoint(_d, true, series.data.length >= showStatusLength);
                                if(series.data.length >= showStatusLength)
                                    _curlst.shift();//remove the first element
                                _curlst.push(rets.data[0]);
                            }else{
                                // var points = getInitCpuStatusData(rets.data);
                                var points = getInitCpuStatusData1( rets.data) ;
                                for(var i=0; i<points.length;i++){
                                    series.addPoint(points[i], true, series.data.length >= showStatusLength);

                                    if(series.data.length >= showStatusLength)
                                        _curlst.shift();
                                    _curlst.push(rets.data[i]);
                                }
                                if(_curlst.length >= showStatusLength){
                                    _curlst.shift();
                                    _curlst.push(rets.data[rets.data.length - 1]);
                                }
                            }
                        }

                    });
                }
               // cpuloadInterval = setTimeout(load,IntervalSec*1000,id);
                cpuloadInterval = timer(load,IntervalSec,id );

            }
        }

        $scope.memorySeries = [{
            name:'memory',
            data:[]
        }];
        $scope.memloadfunc = function () {

            var series = this.series[0];
            var _curlst = [];

            $scope.$watch('curId', function(newValue, oldValue) {
                if(newValue != undefined){
                    load(newValue);
                }

            });
            function load(id) {

                if(series.data.length === 0){
                    monitorService.getMemStatusDatas(id,0,20 ,$scope.svc.dbJson.node.clusterId).then(function(rets){

                        _curlst = rets.data.slice();
                        var points = getInitMemStatusData(_curlst);
                        points.forEach(function(one){
                            series.addPoint(one, true, series.data.length >= showStatusLength);
                        });
                    });
                }else{
                    monitorService.getMemStatusDatas(id,20,IntervalSec ,$scope.svc.dbJson.node.clusterId).then(function(rets){
                        if(rets.data.length != 0){
                            var points = getInitMemStatusData(rets.data);
                            for(var i=0; i<points.length;i++){
                                series.addPoint(points[i], true, series.data.length >= showStatusLength);
                                if(series.data.length >= showStatusLength)
                                    _curlst.shift();
                                _curlst.push(rets.data[i]);
                            }
                        }

                    });
                }
                //timer to refresh the data
                //memloadInterval = setTimeout(load,IntervalSec*1000,id);
                memloadInterval = timer(load,IntervalSec,id) ;
            }

        }

        $scope.networkSeries_rx = [
            {
                name:'Received bytes',
                data:[]
            }
        ]
        $scope.networkloadfunc_rx = function(){

            var series = this.series[0];
            //var series_Rx = this.series[1];
            var IsIdChanged = false;
            var _curlst = [];

            $scope.$watch('curItem', function(newValue, oldValue) {
                IsIdChanged = true;
                if(newValue != undefined){
                    console.log('change to '+newValue.id);
                    if(networkrxloadInterval != undefined)
                        clearTimeout(networkrxloadInterval);
                    load();
                }

            });

            function load() {
                if($scope.curItem.id !== undefined){
                    if(series.data.length === 0 || IsIdChanged === true){
                        monitorService.getNTRxStatusDatas($scope.curItem.id,0,20,$scope.svc.dbJson.node.clusterId).then(function(rets){

                            _curlst = rets.data.slice();
                            var points = getInitNetWorkStatusData(_curlst);
                            points.forEach(function(one){
                                series.addPoint(one, true, series.data.length >= showStatusLength);
                            });
                            IsIdChanged = false;
                        });
                    }else{
                        monitorService.getNTRxStatusDatas($scope.curItem.id,IntervalSec,20 ,$scope.svc.dbJson.node.clusterId).then(function(rets){
                            if(rets.data.length != 0){
                                if(rets.data.length == 1){
                                    var _d = getNetWorkStatusData(_curlst[_curlst.length - 1],rets.data[0]);
                                    series.addPoint(_d, true, series.data.length >= showStatusLength);
                                    if(series.data.length >= showStatusLength)
                                        _curlst.shift();
                                    _curlst.push(rets.data[0]);
                                }else{
                                    var points = getInitNetWorkStatusData(rets.data);
                                    for(var i=0; i<points.length;i++){
                                        series.addPoint(points[i], true, series.data.length >= showStatusLength);
                                        if(series.data.length >= showStatusLength)
                                            _curlst.shift();
                                        _curlst.push(rets.data[i]);
                                    }
                                    if(_curlst.length >= showStatusLength){
                                        _curlst.shift();
                                        _curlst.push(rets.data[rets.data.length - 1]);
                                    }
                                }
                            }

                        });
                    }
                }

                //networkloadInterval = setTimeout(load,IntervalSec*1000);
                networkrxloadInterval = timer(load,IntervalSec) ;
            }

        }

        $scope.networkSeries_tx = [
            {
                name:'Sent bytes',
                data:[]
            }
        ]
        $scope.networkloadfunc_tx = function(){

            var series = this.series[0];
            //var series_Rx = this.series[1];

            var IsIdChanged = false;
            var _curlst = [];

            $scope.$watch('curItem', function(newValue, oldValue) {
                IsIdChanged = true;
                if(newValue != undefined){
                    console.log('change to '+newValue.id);
                    if(networkloadInterval != undefined)
                        clearTimeout(networkloadInterval);
                    load();
                }

            });

            function load() {
                if($scope.curItem.id !== undefined){
                    if(series.data.length === 0 || IsIdChanged === true){
                        monitorService.getNTTxStatusDatas($scope.curItem.id,0,20 ,$scope.svc.dbJson.node.clusterId).then(function(rets){

                            _curlst = rets.data.slice();
                            var points = getInitNetWorkStatusData(_curlst);
                            points.forEach(function(one){
                                series.addPoint(one, true, series.data.length >= showStatusLength);
                            });
                            IsIdChanged = false;
                        });
                    }else{
                        monitorService.getNTTxStatusDatas($scope.curItem.id,IntervalSec ,20,$scope.svc.dbJson.node.clusterId).then(function(rets){
                            if(rets.data.length != 0){
                                if(rets.data.length == 1){
                                    var _d = getNetWorkStatusData(_curlst[_curlst.length - 1],rets.data[0]);
                                    series.addPoint(_d, true, series.data.length >= showStatusLength);
                                    if(series.data.length >= showStatusLength)
                                        _curlst.shift();
                                    _curlst.push(rets.data[0]);
                                }else{
                                    var points = getInitNetWorkStatusData(rets.data);
                                    for(var i=0; i<points.length;i++){
                                        series.addPoint(points[i], true, series.data.length >= showStatusLength);
                                        if(series.data.length >= showStatusLength)
                                            _curlst.shift();
                                        _curlst.push(rets.data[i]);
                                    }
                                    if(_curlst.length >= showStatusLength){
                                        _curlst.shift();
                                        _curlst.push(rets.data[rets.data.length - 1]);
                                    }
                                }
                            }

                        });
                    }
                }
                //networkloadInterval = setTimeout(load,IntervalSec*1000);
                networkloadInterval = timer(load,IntervalSec) ;
            }

        }

        $scope.$on('$destroy', function(){
            console.log("Monitor instance is destoring ... ")
            if (cpuloadInterval !== undefined){
                clearTimeout(cpuloadInterval);
            }
            if (memloadInterval !== undefined)
                clearTimeout(memloadInterval);
            if (networkloadInterval !== undefined)
                clearTimeout(networkloadInterval);
            if( networkrxloadInterval !== undefined ){
                clearTimeout( networkrxloadInterval ) ;
            }
        });
        //获取CpuStatus增量数据数组
        // #rfc160923:the delta of the prev and cur is 0,so there will be a list of 0s.
        function getInitCpuStatusData(status){
            console.log("getInitCpuStatusData invoked...") ;
            var _ret = [];
            if(status.length !== 0){
                for (var i = 1; i < status.length; i++) {
                    var cur = status[i];
                    var prev = status[i - 1];
                    if(cur !== prev)
                        _ret.push(getCpuStatusData(prev,cur));
                }
            }
            return _ret;
        }
        //cpu占用，以秒为单位
        function getInitCpuStatusData1(status){
            var _ret = [];
            if(status.length !== 0){
                for (var i = 0; i < status.length; i++) {
                    var cur = status[i];
                    _ret.push(getCpuStatusData1(cur ));
                }
            }
            return _ret;
        }

        /**
         * 获取NetWorkStatus增量数据数组
         * @param status
         * @returns {Array}
         */
        function getInitMemStatusData(status){
            var _ret = [];
            if(status.length !== 0) {
                for (var i = 0; i < status.length; i++) {
                    var cur = status[i];
                    _ret.push(getMemStatusData(cur));
                }
            }
            return _ret;
        }

        /**
         * 获取NetWorkStatus增量数据数组
         * @param status
         * @returns {Array}
         */
        function getInitNetWorkStatusData(status){
            var _ret = [];
            if(status.length !== 0) {
                for (var i = 1; i < status.length; i++) {
                    var cur = status[i];
                    var prev = status[i - 1];
                    _ret.push(getNetWorkStatusData(prev,cur));
                }
            }
            return _ret;
        }

        /**
         * get delta between prev and cur
         * @param prev
         * @param cur
         * @returns difference
         */
        function getCpuStatusData(prev,cur,nodelta){
            //0 is timestamp   1 is value
            var intervalInNs = getInterval(cur[0], prev[0]);
            var elements = [];
            elements.push(new Date(cur[0]).getTime());
            if( nodelta === undefined || !nodelta  ){
                elements.push((cur[1] - prev[1]) / intervalInNs);
            }else{
                elements.push(( prev[1]) / intervalInNs);
            }
            return elements;
        }
        function getCpuStatusData1(cur){
            var elements = [];
            elements.push(new Date(cur[0]).getTime());
            elements.push((cur[1] ) / 1000000000);
            return elements;
        }

        function getMemStatusData(cur){
            var elements = [];
            elements.push(new Date(cur[0]).getTime());
            elements.push(cur[1] / oneMegabyte);
            return elements;
        }

        function getNetWorkStatusData(prev,cur){

            var intervalInSec = getInterval(cur[0], prev[0]) / 1000000000;//nano seconds
            var elements = [];
            elements.push(new Date(cur[0]).getTime());
            elements.push((cur[1] - prev[1]) / intervalInSec);
            return elements;
        }

        /**
         * Gets the length of the interval in nanoseconds.
         * @param current
         * @param previous
         * @returns {number}
         */
        function getInterval(current, previous) {
            var cur = new Date(current);
            var prev = new Date(previous);

            // ms -> ns.
            return (cur.getTime() - prev.getTime()) * 1000000;
        }


        // $scope.init = function(idx){
        //     _setLoadDataEvt(idx);
        // }
        /**
         * Controller initializing
         * @param idx
         * @private
         */
        // function _setLoadDataEvt(idx){
            $scope.$on('getMonitorEvt',function(event,item){
              $scope.loadonce = false;
              console.log("listen on getMonitorEvt"+",and loadonce="+$scope.loadonce) ;
                if(!$scope.loadonce) {
                    $scope.loadonce = true;
                    $scope.curId = item.metadata.name;
                    $scope.curItem = {
                        replicasname:item.metadata.name,
                        phase:item.status.phase,
                        lastState:{},
                        hostIP:item.status.hostIP,
                        $$hashKey:item.$$hashKey

                    } ;


                    //accept a Monitor-Evt,then change $scope.curItem
                    // item's format just like :
                    // {
                    //     "replicasname" : "vn-v1.9.14-alpine-xxh13",
                    //     "phase" : "running",
                    //     "lastState" : {},
                    //     "hostIP" : "10.169.24.118",
                    //     "$$hashKey" : "object:33"
                    // }
                    //TODO there is not any id field in the item object ,but  $scope.networkloadfunc_xx function required this field
                    //TODO so here assign the replicasname to id ,when there is a id in the item object ,then use it latter.
                    if(  ! $scope.curItem.id ){
                        $scope.curItem.id =  $scope.curId ;
                    }
                    //console.log( ">>accept monitor event >> $scope.curItem"+JSON.stringify( $scope.curItem ) ) ;
                    //$scope.cpuloadfunc(item.replicasname);

                }
            });
        // }

        function timer(cb,interval,id){
            if( id ){
                //console.log( "id="+id) ;
                return setTimeout(function(){cb(id);},interval*1000);
            }else{
                return setTimeout( cb ,interval*1000);
            }

        }


});